home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-13 / thesrc10.zip / FNMATCH.C < prev    next >
C/C++ Source or Header  |  1992-08-04  |  4KB  |  178 lines

  1. /* Copyright (C) 1991 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3.  
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public License as
  6. published by the Free Software Foundation; either version 2 of the
  7. License, or (at your option) any later version.
  8.  
  9. The GNU C Library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12. Library General Public License for more details.
  13.  
  14. You should have received a copy of the GNU Library General Public
  15. License along with the GNU C Library; see the file COPYING.LIB.  If
  16. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  17. Cambridge, MA 02139, USA.  */
  18.  
  19. /*  */
  20. #include <errno.h>
  21. #include <fnmatch.h>
  22.  
  23. #if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS)
  24. extern int errno;
  25. #endif
  26.  
  27. /* Match STRING against the filename pattern PATTERN, returning zero if
  28.    it matches, nonzero if not.  */
  29. int
  30. fnmatch(pattern, string, flags)
  31.      char *pattern;
  32.      char *string;
  33.      int flags;
  34. {
  35.   register char *p = pattern, *n = string;
  36.   register char c;
  37.  
  38.   if ((flags & ~__FNM_FLAGS) != 0)
  39.     {
  40.       errno = EINVAL;
  41.       return -1;
  42.     }
  43.  
  44.   while ((c = *p++) != '\0')
  45.     switch (c)
  46.       {
  47.       case '?':
  48.     if (*n == '\0')
  49.       return FNM_NOMATCH;
  50.     else if ((flags & FNM_PATHNAME) && *n == '/')
  51.       return FNM_NOMATCH;
  52.     else if ((flags & FNM_PERIOD) && *n == '.' &&
  53.          (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
  54.       return FNM_NOMATCH;
  55.     else
  56.       ++n;
  57.     break;
  58.  
  59.       case '\\':
  60.     if (!(flags & FNM_NOESCAPE))
  61.       c = *p++;
  62.     if (*n++ != c)
  63.       return FNM_NOMATCH;
  64.     break;
  65.  
  66.       case '*':
  67.     if ((flags & FNM_PERIOD) && *n == '.' &&
  68.         (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
  69.       return FNM_NOMATCH;
  70.  
  71.     for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
  72.       if (((flags & FNM_PATHNAME) && *n == '/') ||
  73.           (c == '?' && *n == '\0'))
  74.         return FNM_NOMATCH;
  75.  
  76.     if (c == '\0')
  77.       return 0;
  78.  
  79.     {
  80.       char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
  81.       for (--p; *n != '\0'; ++n)
  82.         if ((c == '[' || *n == c1) &&
  83.         fnmatch(p, n, flags & ~FNM_PERIOD) == 0)
  84.           return 0;
  85.       return FNM_NOMATCH;
  86.     }
  87.  
  88.       case '[':
  89.     {
  90.       /* Nonzero if this if the sense of
  91.          the character class is inverted.  */
  92.       register int not;
  93.  
  94.       if (*n == '\0')
  95.         return FNM_NOMATCH;
  96.  
  97.       if ((flags & FNM_PERIOD) && *n == '.' &&
  98.           (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
  99.         return FNM_NOMATCH;
  100.  
  101.       not = *p == '!';
  102.       if (not)
  103.         ++p;
  104.  
  105.       c = *p++;
  106.       for (;;)
  107.         {
  108.           register char cstart = c, cend = c;
  109.  
  110.           if (!(flags & FNM_NOESCAPE) && c == '\\')
  111.         cstart = cend = *p++;
  112.  
  113.           if (c == '\0')
  114.         /* [ (unterminated) loses.  */
  115.         return FNM_NOMATCH;
  116.  
  117.           c = *p++;
  118.           if ((flags & FNM_PATHNAME) && c == '/')
  119.         /* [/] can never match.  */
  120.         return FNM_NOMATCH;
  121.  
  122.           if (c == '-')
  123.         {
  124.           cend = *p++;
  125.           if (!(flags & FNM_NOESCAPE) && cend == '\\')
  126.             cend = *p++;
  127.           if (cend == '\0')
  128.             return FNM_NOMATCH;
  129.           c = *p++;
  130.         }
  131.           if (*n >= cstart && *n <= cend)
  132.         goto matched;
  133.  
  134.           if (c == ']')
  135.         break;
  136.         }
  137.       if (!not)
  138.         return FNM_NOMATCH;
  139.       break;
  140.  
  141.     matched:;
  142.       /* Skip the rest of the [...] that already matched.  */
  143.       while (c != ']')
  144.         {
  145.           if (c == '\0')
  146.         /* [... (unterminated) loses.  */
  147.         return FNM_NOMATCH;
  148.  
  149.           c = *p++;
  150.           if (!(flags & FNM_NOESCAPE) && c == '\\')
  151.         /* 1003.2d11 is unclear if this is right.  %%% */
  152.         ++p;
  153.         }
  154.       if (not)
  155.         return FNM_NOMATCH;
  156.  
  157.       ++n;
  158.     }
  159.     break;
  160.  
  161.       default:
  162.     if ((flags & FNM_IGNORECASE))                     /* MH */
  163.       {                                               /* MH */
  164.        if (toupper(c) != toupper(*n++))               /* MH */
  165.           return FNM_NOMATCH;                         /* MH */
  166.       }                                               /* MH */
  167.     else                                              /* MH */
  168.        if (c != *n++)
  169.           return FNM_NOMATCH;
  170.  
  171.       }
  172.  
  173.   if (*n == '\0')
  174.     return 0;
  175.  
  176.   return FNM_NOMATCH;
  177. }
  178.